sockaddr

您所在的位置:网站首页 struct in6_addr结构体 sockaddr

sockaddr

2023-04-06 18:25| 来源: 网络整理| 查看: 265

背景:在muduo库中,InetAddress类是一个包含socket地址的数据类型,包括这个ip地址和端口号。

在里面有一个表示socket地址的union。

1 private: 2 union 3 { 4 struct sockaddr_in addr_; 5 struct sockaddr_in6 addr6_; 6 };

当时觉得这个很奇怪,因为这个东西仅仅就是定义了一种数据类型,并没有定义一个对应的变量,这个怎么用呢?

经查证 这是一个匿名的联合体,有其特殊的用法。

参见: https://www.cnblogs.com/guozqzzu/p/3626893.html

--------------------------------------------------------------------------------------------------

Anonymous unions—匿名联合

在 C++ 我们可以选择使联合(union)匿名。如果我们将一个 union 包括在一个结构(structure)的定义中,并且不赋予它对象(object)名称 (就是跟在

花括号{}后面的名字),这个union 就是匿名的。这种情况下我们可以直接使用 union 中元素的名字来访问该元素,而不需要再在前面加 union 对象的名称。

在下面的例子中,我们可以看到这两种表达方式在使用上的区别:

 

union anonymous union struct { char title[50]; char author[50]; union { float dollars; int yen; } price; } book; struct { char title[50]; char author[50]; union { float dollars; int yen; }; } book;

 

以上两种定义的唯一区别在于左边的定义中我们给了 union 一个名字 price ,而在右边的定义中我们没给。

在使用时的区别是当我们想访问一个对象(object)的元素 dollars 和 yen 时,在前一种定义的情况下,需要使用:

 

    book.price.dollars;

    book.price.yen;

而在后面一种定义下,我们直接使用:

    book.dollars;

    book.yen;

 

再一次提醒,因为这是一个联合(union),域 dollars 和 yen 占据的是同一块内存空间,所以它们不能被用来存储两个不同的值。也就是你可以使用

一个 dollars 或 yen 的价格,但不能同时使用两者。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

总结:

1. 不管是匿名的联合体或者是命名的联合体都是共用同一段内存。

2. 匿名的联合体按照联合体内的变量直接使用不使用点 . 运算符,联合体内的变量共享内存且同时只能使用一个。

 

下面来看一下结构体 sockaddr_in 和 sockaddr_in6 的区别:

首先在在网络编程中是怎样来表示socket地址的呢?

#include struct sockaddr { sa_family_t sa_family; char sa_data[14]; } sa_family是 地址族类型sa_family_t 的变量: 指示是Ipv4(AF_INET)还是ipv6(AF_INET6).

------------------------------------------------------

地址族与协议族:PF_INET  -----  AF_INET   --------   ipv4  ------ 16bit端口号和32bit ipv4地址共6个字节

PF_INET6 -----  AF_INET6 -------- ipv6 ------ 16bit端口号和32bit流标识 128bit ipv6地址,32bit范围ID共26字节PF开头的宏和AF开头的宏通常拥有一样的值所以二者经常混用。------------------------------------------ sa_data:保存真正的socket地址。 只有14个字节

从上面的规定可以看出,这个经典的结构体的大小是不能保存ipv6的,因为他拥有的内存不足以保存。这样的话就没有一个通用的结构体可以放下所有的地址,在LINUX中重新定义了一个结构体:

1 #include 2 struct sockaddr_storage 3 { 4 sa_family_t sa_family; 5 unsigned long int __ss_align; 6 char __ss_padding[128-sizeof(__ss_align)]; 7 }

按照书上的解释:

这个结构体不仅提供了足够大的空间用于存放地址值,而且是内存对齐的(这是__ss_align成员的作用)

 

三个问题:

1. 是如何提供了足够大的空间。

2. 什么是内存对齐,为什么要对齐。

3. __ss_align究竟起到了什么作用。

下面根据我的理解来回答这些问题。

首先,这个结构体里面保存了两种形式的数据,一个是协议族的类型,另一个是一个socket的套接字地址。

__ss_align就是起到有个对齐的作用,一个结构体有两个对齐的形式,一个是结构体本身的对齐,另一个是结构体内的成员之间的对齐,根据之前学习的知识。结构体内的成员按照其自身的对齐规则对齐,结构体本身的初始地址按照成员的最大对齐宽度对齐。

所以这里的

__ss_align确实是起到了对齐的作用,但是有什么用呢?

经查阅资料 说是为了统一操作,包括根据起始地址读取数据的偏移等。

引:

SOCKADDR_STORAGE可以包含IPv6或IPv4地址,并适当填充该结构以实现64位对齐。这样的对齐使特定于协议的套接字地址数据结构能够访问SOCKADDR_STORAGE结构内的字段,而不会出现对齐问题。通过填充,SOCKADDR_STORAGE结构的长度为128个字节。

以上两个是通用的socket套接字地址表示法。书上说这个显然不好用,主要体现在:1. 读取ip地址和端口号的时候需要进行繁琐的位操作。

LINUX为各个协议族提供了专门的socket地址结构体。

专用的socket地址1. unix本地域协议族使用如下专用socket地址结构体:

1 #include 2 struct sockaddr_un 3 { 4 sa_family_t sin_family; /* 地址族:AF_UNIX */ 5 char sun_path[108]; /*文件路径名*/ 6 };

 

2. TCP/IP 协议簇的ipv4地址表示法:

struct sockaddr_in { sa_family_t sin_family; /* 地址族:AF_UNIX */ u_int16_t sin_port; /* 端口号: 要用网络直接序表示 */ struct in_addr sin_addr; /* ipv4地址结构体, 见下面 */ };

其中 struct in_addr 如下:

struct in_addr { u_int32_t s_addr; /* ipv4地址, 要用网络字节序表示 */ };

以上不难看出这个32Bit的空间  是一个用于存放ipv4地址的经过简单封装的结构体。

3. ipv6的地址表示结构体:

1 struct sockaddr_in6 2 { 3 sa_family_t sin6_family; /* 地址协议簇: AF_INET6 */ 4 u_int16_t sin6_port; /* 端口号, 要用网络字节序表示 */ 5 u_int32_t sin6_flowinfo /* 流信息, 应设置为0 */ 6 struct in6_addr sin6_addr; /* ipv6 地址结构体, 见下面 */ 7 u_int32_t sin6_socpe_id; /* scope ID, 尚处于实验阶段 */ 8 }; 9 10 struct in6_addr 11 { 12 unsigned char sa_addr[16]; /* ipv6地址, 要使用网络字节序表示 */ 13 };

以上ipv6的表示形式比ipv4要复杂了许多,但大同小异,那些附加的用法暂时不想去管它。

 

总结: 专用地址格式意义明确也好用一些。

 

专用的socket地址和通用地址的关系

引用:

所有专用的socket地址结构体(以及sockaddr_storage)类型的变量在实际使用中都需要转化为最通用的socket地址类型sockaddr(强制转换即可),因为所有socket编程接口使用的地址参数的类型都是sockaddr.

   

 

 

 

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3